Web 上で最初の Flutter アプリを作成する
これは、最初の Flutter を作成するためのガイドですウェブアプリ。 オブジェクト指向プログラミングに精通している場合は、 変数、ループ、条件などの概念、 このチュートリアルを完了できます。 Dart の経験は必要ありません。 モバイルまたはウェブプログラミング。
構築するもの
サインイン画面を表示する単純な Web アプリを実装します。 画面には、名、名前、 姓とユーザー名。ユーザーがフィールドに入力すると、 進行状況バーがサインイン領域の上部に沿ってアニメーション表示されます。 3 つのフィールドすべてに入力すると、進行状況バーが表示されます。 サインインエリアの全幅に沿って緑色で表示されます。 そしてそのサインアップボタンが有効になります。 をクリックすると、サインアップボタンをクリックするとようこそ画面が表示されます 画面の下からアニメーション化します。
アニメーション GIF は、このラボの完了時にアプリがどのように動作するかを示しています。
ステップ 0: スターター Web アプリを入手する
私たちが提供するシンプルな Web アプリから始めます。
-
Web 開発を有効にします。
コマンドラインで次のコマンドを実行して、 Flutter が正しくインストールされていることを確認してください。$ flutter doctor Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel master, 3.4.0-19.0.pre.254, on macOS 12.6 21G115 darwin-arm64, locale en) [✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 14.0) [✓] Chrome - develop for the web [✓] Android Studio (version 2021.2) [✓] VS Code (version 1.71.1) [✓] Connected device (4 available) [✓] HTTP Host Availability • No issues found!
「flutter: コマンドが見つかりません」と表示された場合は、 次に、インストールされていることを確認してください flutterSDKそしてそれがあなたの行く手にあることを。
Android ツールチェーンである Android Studio であれば問題ありません。 Xcode ツールがインストールされていない場合、 アプリはウェブのみを対象としているためです。 後でこのアプリをモバイルでも動作させたい場合は、 追加のインストールとセットアップを行う必要があります。
-
デバイスをリストします。
ウェブを確実にするにははインストールされている、 利用可能なデバイスをリストします。 次のようなものが表示されるはずです。$ flutter devices 4 connected devices: sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 13 (API 33) (emulator) iPhone 14 Pro Max (mobile) • 45A72BE1-2D4E-4202-9BB3-D6AE2601BEF8 • ios • com.apple.CoreSimulator.SimRuntime.iOS-16-0 (simulator) macOS (desktop) • macos • darwin-arm64 • macOS 12.6 21G115 darwin-arm64 Chrome (web) • chrome • web-javascript • Google Chrome 105.0.5195.125
のクロムデバイスは自動的に Chrome を起動し、使用できるようにします Flutter DevTools ツールの。
-
以下のDartPadに起動アプリが表示されます。
{$ begin main.dart $} import 'package:flutter/material.dart'; void main() => runApp(const SignUpApp()); class SignUpApp extends StatelessWidget { const SignUpApp(); @override Widget build(BuildContext context) { return MaterialApp( routes: { '/': (context) => const SignUpScreen(), }, ); } } class SignUpScreen extends StatelessWidget { const SignUpScreen(); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey[200], body: const Center( child: SizedBox( width: 400, child: Card( child: SignUpForm(), ), ), ), ); } } class SignUpForm extends StatefulWidget { const SignUpForm(); @override State<SignUpForm> createState() => _SignUpFormState(); } class _SignUpFormState extends State<SignUpForm> { final _firstNameTextController = TextEditingController(); final _lastNameTextController = TextEditingController(); final _usernameTextController = TextEditingController(); double _formProgress = 0; @override Widget build(BuildContext context) { return Form( child: Column( mainAxisSize: MainAxisSize.min, children: [ LinearProgressIndicator(value: _formProgress), Text('Sign up', style: Theme.of(context).textTheme.headlineMedium), Padding( padding: const EdgeInsets.all(8), child: TextFormField( controller: _firstNameTextController, decoration: const InputDecoration(hintText: 'First name'), ), ), Padding( padding: const EdgeInsets.all(8), child: TextFormField( controller: _lastNameTextController, decoration: const InputDecoration(hintText: 'Last name'), ), ), Padding( padding: const EdgeInsets.all(8), child: TextFormField( controller: _usernameTextController, decoration: const InputDecoration(hintText: 'Username'), ), ), TextButton( style: ButtonStyle( foregroundColor: MaterialStateProperty.resolveWith( (Set<MaterialState> states) { return states.contains(MaterialState.disabled) ? null : Colors.white; }), backgroundColor: MaterialStateProperty.resolveWith( (Set<MaterialState> states) { return states.contains(MaterialState.disabled) ? null : Colors.blue; }), ), onPressed: null, child: const Text('Sign up'), ), ], ), ); } } {$ end main.dart $} {$ begin test.dart $} // Avoid warning on "double _formProgress = 0;" //ignore_for_file: prefer_final_fields {$ end test.dart $}
-
例を実行します。
クリック走るボタンをクリックして例を実行します。 テキストフィールドに入力できることに注意してください。 しかしサインアップボタンが無効になっています。 -
コードをコピーします。
右上にあるクリップボードアイコンをクリックします。 コードペインを使用して、Dart コードをクリップボードにコピーします。 -
新しい Flutter プロジェクトを作成します。
IDE、エディター、またはコマンドラインから、新しい Flutter プロジェクトを作成するそしてそれに名前を付けますsignin_example
。 -
の内容を置き換えます
lib/main.dart
クリップボードの内容とともに。
観察
- この例のコード全体は、
lib/main.dart
ファイル。 - Java を知っている人であれば、Dart 言語は非常に親しみのあるものに感じられるはずです。
- アプリの UI はすべて Dart コードで作成されます。 詳細については、を参照してください。宣言型 UI の概要。
- アプリのUIは以下に準拠していますマテリアルデザイン、 あらゆるデバイスやプラットフォームで動作するビジュアル デザイン言語。 マテリアル デザイン ウィジェットをカスタマイズできます。 でも、他のものが好みなら、 Flutter は、Cupertino ウィジェット ライブラリも提供しています。 現在の iOS デザイン言語を実装します。 または、独自のカスタム ウィジェット ライブラリを作成することもできます。
- Flutter では、ほとんどすべてがウィジェット。 アプリ自体もウィジェットです。 アプリの UI はウィジェット ツリーとして説明できます。
ステップ 1: ようこそ画面を表示する
のSignUpForm
クラスはステートフルなウィジェットです。
これは単にウィジェットに情報が保存されることを意味します。
ユーザー入力やフィードからのデータなど、変更される可能性のあるもの。
ウィジェット自体は不変なので
(作成後に変更することはできません)、
Flutter は状態情報をコンパニオンクラスに保存します。
と呼ばれるState
クラス。この研究室では、
すべての編集は非公開に対して行われます_SignUpFormState
クラス。
まず、あなたの中でlib/main.dart
ファイル、
次のクラス定義を追加します。WelcomeScreen
後のウィジェットSignUpScreen
クラス:
class WelcomeScreen extends StatelessWidget {
const WelcomeScreen();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child:
Text('Welcome!', style: Theme.of(context).textTheme.displayMedium),
),
);
}
}
次に、画面を表示するボタンを有効にします。 そしてそれを表示するメソッドを作成します。
-
を見つけます。
build()
の方法_SignUpFormState
クラス。これはコードの一部です これで「SignUp」ボタンが構築されます。 ボタンがどのように定義されているかに注目してください。 それはTextButton
青色の背景で、 という白い文字サインアップそして、押すと、 何もしません。 -
を更新します
onPressed
財産。
変更onPressed
(存在しない) を呼び出すプロパティ ようこそ画面を表示するメソッド。変化
onPressed: null
以下に:onPressed: _showWelcomeScreen,
-
を追加します。
_showWelcomeScreen
方法。
アナライザーによって報告されたエラーを修正します。_showWelcomeScreen
定義されていません。の真上build()
方法、 次の関数を追加します。void _showWelcomeScreen() { Navigator.of(context).pushNamed('/welcome'); }
-
を追加します。
/welcome
ルート。
新しい画面を表示するための接続を作成します。 の中にbuild()
の方法SignUpApp
、 以下のルートを追加します'/'
:'/welcome': (context) => const WelcomeScreen(),
-
アプリを実行します。
のサインアップボタンが有効になるはずです。 それをクリックすると、ようこそ画面が表示されます。 下からどのようにアニメーション化されるかに注目してください。 その動作は無料で行えます。
観察
- の
_showWelcomeScreen()
関数はで使用されますbuild()
メソッドをコールバック関数として使用します。コールバック関数は多くの場合、 Dart コードで使用され、この場合、これは意味します 「ボタンが押されたときにこのメソッドを呼び出す」。 - の
const
コンストラクターの前のキーワードは非常に重要です 重要。 Flutter が定数ウィジェットに遭遇すると、 内部での再構築作業のほとんどをショートさせてしまう レンダリングをより効率的にします。 - Flutter には 1 つだけあります
Navigator
物体。 Flutterの画面を管理するウィジェットです (とも呼ばれているルートまたページ) スタック内。 スタックの一番上の画面は、 現在は が表示されています。新しい画面をこれにプッシュします スタックは表示をその新しい画面に切り替えます。 このため、_showWelcomeScreen
関数プッシュ のWelcomeScreen
ナビゲーターのスタックに追加します。 ユーザーがボタンをクリックすると、出来上がりです。 ようこそ画面が表示されます。同じく、 電話をかけるpop()
でNavigator
に戻ります 前の画面。 Flutterのナビゲーションは ブラウザのナビゲーションに統合されており、 これはブラウザの 戻る矢印ボタン。
ステップ 2: サインイン進行状況の追跡を有効にする
このサインイン画面には 3 つのフィールドがあります。 次に、追跡する機能を有効にします。 ユーザーのフォームフィールドへの入力の進捗状況、 フォームが完了したら、アプリの UI を更新します。
-
更新するメソッドを追加する
_formProgress
。 の中に_SignUpFormState
クラスに、という新しいメソッドを追加します。_updateFormProgress()
:void _updateFormProgress() { var progress = 0.0; final controllers = [ _firstNameTextController, _lastNameTextController, _usernameTextController ]; for (final controller in controllers) { if (controller.value.text.isNotEmpty) { progress += 1 / controllers.length; } } setState(() { _formProgress = progress; }); }
このメソッドは、
_formProgress
に基づくフィールド 空ではないテキストフィールドの数。 -
電話
_updateFormProgress
フォームのとき 変化します。
の中にbuild()
の方法_SignUpFormState
クラス、 にコールバックを追加しますForm
ウィジェットのonChanged
口論。 NEW としてマークされた以下のコードを追加します。return Form( onChanged: _updateFormProgress, // NEW child: Column(
-
を更新します
onPressed
財産(再び)。
のstep 1
を変更しました。onPressed
の財産サインアップボタンをクリックすると、ようこそ画面が表示されます。 次に、そのボタンを更新してようこそを表示します フォームが完全に入力された場合にのみ画面が表示されます。TextButton( style: ButtonStyle( foregroundColor: MaterialStateProperty.resolveWith( (Set<MaterialState> states) { return states.contains(MaterialState.disabled) ? null : Colors.white; }), backgroundColor: MaterialStateProperty.resolveWith( (Set<MaterialState> states) { return states.contains(MaterialState.disabled) ? null : Colors.blue; }), ), onPressed: _formProgress == 1 ? _showWelcomeScreen : null, // UPDATED child: const Text('Sign up'), ),
-
アプリを実行します。
のサインアップボタンは最初は無効になっていますが、 ただし、3 つのテキストフィールドすべてに次の内容が含まれる場合に有効になります。 (任意の) テキスト。
観察
- ウィジェットの呼び出し
setState()
メソッドは Flutter に次のように伝えます。 ウィジェットは画面上で更新する必要があります。 その後、フレームワークは以前の不変ウィジェットを破棄します。 (およびその子)、新しいものを作成します (付随する子ウィジェットツリーを含む)、 そしてそれを画面にレンダリングします。これをシームレスに機能させるには、 flutterは高速である必要があります。 新しいウィジェット ツリーを作成して画面にレンダリングする必要があります 1/60 秒未満で滑らかなビジュアルを作成します トランジション、特にアニメーションの場合。 ラッキー flutterは速い。 - の
progress
フィールドは浮動小数点値として定義されており、 で更新されます_updateFormProgress
方法。 3 つのフィールドをすべて入力すると、_formProgress
は 1.0 に設定されます。 いつ_formProgress
が 1.0 に設定されている場合、onPressed
コールバックはに設定されます_showWelcomeScreen
方法。さて、それはonPressed
引数が null 以外の場合、ボタンは有効になります。 Flutter のほとんどのマテリアル デザイン ボタンと同様、テキストボタンはデフォルトで無効になっています。onPressed
とonLongPress
コールバックは null です。 -
注目してください。
_updateFormProgress
に関数を渡しますsetState()
。 これを匿名といいます 関数であり、次の構文があります。methodName(() {...});
どこ
methodName
匿名を受け取る名前付き関数です。 コールバック関数を引数として指定します。 -
を表示する最後のステップの Dart 構文 ようこそ画面は次のとおりです。
_formProgress == 1 ? _showWelcomeScreen : null
これは Dart の条件付き代入であり、構文は次のとおりです。
condition ? expression1 : expression2
。 式の場合_formProgress == 1
true の場合、式全体の結果は の左側の値に:
、それは_showWelcomeScreen
この場合の方法。
ステップ 2.5: Dart DevTools を起動する
Flutter Web アプリをデバッグするにはどうすればよいですか? これは、Flutter アプリのデバッグとあまり変わりません。 使いたいDart 開発ツール! (Chrome DevTools と混同しないでください。)
私たちのアプリには現時点ではバグはありませんが、とにかくチェックしてみましょう。 DevTools を起動するための次の手順は、どのワークフローにも当てはまります。 ただし、IntelliJ を使用している場合はショートカットがあります。 詳細については、このセクションの最後にあるヒントを参照してください。
-
アプリを実行します。
アプリが現在実行されていない場合は、起動します。 を選択クロムプルダウンからのデバイス IDE から起動するか、 コマンドラインから、使用しますflutter run -d chrome
、 -
DevTools の Web ソケット情報を取得します。
コマンドラインまたはIDEで、 次のようなメッセージが表示されるはずです。Launching lib/main.dart on Chrome in debug mode... Building application for the web... 11.7s Attempting to connect to browser instance.. Debug service listening on ws://127.0.0.1:54998/pJqWWxNv92s=
太字で示されているデバッグ サービスのアドレスをコピーします。 DevTools を起動するにはこれが必要になります。
-
DevTools がインストールされていることを確認します。
ありますか開発ツールがインストールされている? IDE を使用している場合は、 Flutter プラグインと Dart プラグインが設定されていることを確認してください。 で説明されているように、VSコードとAndroid Studio と IntelliJページ。 コマンドラインで作業している場合は、 の説明に従って DevTools サーバーを起動します。DevTools コマンドラインページ。 -
開発ツールに接続します。
DevTools が起動すると、何かが表示されるはずです 次のような:Serving DevTools at http://127.0.0.1:9100
Chrome ブラウザでこの URL にアクセスします。 DevTools が表示されるはずです 起動画面。次のようになります。
-
実行中のアプリに接続します。
下実行中のサイトに接続する、 手順 2 でコピーした ws の場所を貼り付けます。 をクリックし、「接続」をクリックします。 Dart DevTools が表示されるはずです。 Chrome ブラウザで正常に実行されています:おめでとうございます。Dart DevTools を実行できるようになりました。
-
ブレークポイントを設定します。
これで DevTools が実行されました。 を選択デバッガ上部にある青いバーのタブをクリックします。 デバッガー ペインが表示され、左下に この例で使用されているライブラリのリストを参照してください。 選択するlib/main.dart
Dartコードを表示するには 中央のペインにあります。 -
ブレークポイントを設定します。
ダーツコードでは、 どこまで下にスクロールしますprogress
更新されます:for (final controller in controllers) { if (controller.value.text.isNotEmpty) { progress += 1 / controllers.length; } }
をクリックして、for ループのある行にブレークポイントを配置します。 行番号の左側。ブレークポイントが表示されます の中にブレークポイントウィンドウの左側のセクション。
-
ブレークポイントをトリガーします。
実行中のアプリで、テキスト フィールドの 1 つをクリックしてフォーカスを取得します。 アプリがブレークポイントに到達し、一時停止します。 DevTools 画面の左側に表示されます。 の値progress
、これは 0 です。これは予想されることですが、 どのフィールドも入力されていないためです。 for ループを実行して確認します プログラムの実行。 -
アプリを再開します。
緑色のアイコンをクリックしてアプリを再開します履歴書DevTools ウィンドウのボタン。 -
ブレークポイントを削除します。
もう一度クリックしてブレークポイントを削除し、アプリを再開します。
これにより、DevTools を使用して何が可能になるかを少し垣間見ることができます。 他にもたくさんあります!詳細については、 を参照してください開発ツールのドキュメント。
ステップ 3: サインイン中のアニメーションを追加する
アニメーションを追加する時が来ました!この最後のステップでは、
のアニメーションを作成しますLinearProgressIndicator
サインインの上部にある
エリア。アニメーションは次のような動作をします。
- アプリが起動すると、 サインイン領域の上部に小さな赤いバーが表示されます。
- 1 つのテキスト フィールドにテキストが含まれている場合、 赤いバーがオレンジ色に変わり、0.15 がアニメーション化されます。 サインインエリアを横切る途中。
- 2 つのテキスト フィールドにテキストが含まれている場合、 オレンジ色のバーが黄色に変わり、半分がアニメーションします サインインエリアを横切る途中。
- 3 つのテキスト フィールドすべてにテキストが含まれている場合、 オレンジ色のバーが緑色に変わり、すべての要素がアニメーション化されます。 サインインエリアを越えて。 また、サインアップボタンが有効になります。
-
を追加
AnimatedProgressIndicator
。
ファイルの最後に、次のウィジェットを追加します。class AnimatedProgressIndicator extends StatefulWidget { final double value; const AnimatedProgressIndicator({ required this.value, }); @override State<AnimatedProgressIndicator> createState() { return _AnimatedProgressIndicatorState(); } } class _AnimatedProgressIndicatorState extends State<AnimatedProgressIndicator> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<Color?> _colorAnimation; late Animation<double> _curveAnimation; @override void initState() { super.initState(); _controller = AnimationController( duration: Duration(milliseconds: 1200), vsync: this); final colorTween = TweenSequence([ TweenSequenceItem( tween: ColorTween(begin: Colors.red, end: Colors.orange), weight: 1, ), TweenSequenceItem( tween: ColorTween(begin: Colors.orange, end: Colors.yellow), weight: 1, ), TweenSequenceItem( tween: ColorTween(begin: Colors.yellow, end: Colors.green), weight: 1, ), ]); _colorAnimation = _controller.drive(colorTween); _curveAnimation = _controller.drive(CurveTween(curve: Curves.easeIn)); } @override void didUpdateWidget(oldWidget) { super.didUpdateWidget(oldWidget); _controller.animateTo(widget.value); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: _controller, builder: (context, child) => LinearProgressIndicator( value: _curveAnimation.value, valueColor: _colorAnimation, backgroundColor: _colorAnimation.value?.withOpacity(0.4), ), ); } }
の
didUpdateWidget
機能アップデート のAnimatedProgressIndicatorState
いつでもAnimatedProgressIndicator
変化します。 -
新しいものを使用してください
AnimatedProgressIndicator
。
次に、LinearProgressIndicator
の中にForm
この新しいものでAnimatedProgressIndicator
:child: Column( mainAxisSize: MainAxisSize.min, children: [ AnimatedProgressIndicator(value: _formProgress), // NEW Text('Sign up', style: Theme.of(context).textTheme.headlineMedium), Padding(
このウィジェットは
AnimatedBuilder
アニメーション化する 最新値への進行状況インジケーター。 -
アプリを実行します。
3 つのフィールドに何かを入力して確認します。 アニメーションが動作し、サインアップボタンが表示されますいらっしゃいませ画面。
完全なサンプル
import 'package:flutter/material.dart';
void main() => runApp(const SignUpApp());
class SignUpApp extends StatelessWidget {
const SignUpApp();
@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'/': (context) => const SignUpScreen(),
'/welcome': (context) => const WelcomeScreen(),
},
);
}
}
class SignUpScreen extends StatelessWidget {
const SignUpScreen();
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[200],
body: Center(
child: SizedBox(
width: 400,
child: Card(
child: SignUpForm(),
),
),
),
);
}
}
class WelcomeScreen extends StatelessWidget {
const WelcomeScreen();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child:
Text('Welcome!', style: Theme.of(context).textTheme.displayMedium),
),
);
}
}
class SignUpForm extends StatefulWidget {
@override
State<SignUpForm> createState() => _SignUpFormState();
}
class _SignUpFormState extends State<SignUpForm> {
final _firstNameTextController = TextEditingController();
final _lastNameTextController = TextEditingController();
final _usernameTextController = TextEditingController();
double _formProgress = 0;
void _updateFormProgress() {
var progress = 0.0;
final controllers = [
_firstNameTextController,
_lastNameTextController,
_usernameTextController
];
for (final controller in controllers) {
if (controller.value.text.isNotEmpty) {
progress += 1 / controllers.length;
}
}
setState(() {
_formProgress = progress;
});
}
void _showWelcomeScreen() {
Navigator.of(context).pushNamed('/welcome');
}
@override
Widget build(BuildContext context) {
return Form(
onChanged: _updateFormProgress,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
AnimatedProgressIndicator(value: _formProgress),
Text('Sign up', style: Theme.of(context).textTheme.headlineMedium),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: _firstNameTextController,
decoration: const InputDecoration(hintText: 'First name'),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: _lastNameTextController,
decoration: const InputDecoration(hintText: 'Last name'),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: _usernameTextController,
decoration: const InputDecoration(hintText: 'Username'),
),
),
TextButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.resolveWith(
(Set<MaterialState> states) {
return states.contains(MaterialState.disabled)
? null
: Colors.white;
}),
backgroundColor: MaterialStateProperty.resolveWith(
(Set<MaterialState> states) {
return states.contains(MaterialState.disabled)
? null
: Colors.blue;
}),
),
onPressed: _formProgress == 1 ? _showWelcomeScreen : null,
child: const Text('Sign up'),
),
],
),
);
}
}
class AnimatedProgressIndicator extends StatefulWidget {
final double value;
const AnimatedProgressIndicator({
required this.value,
});
@override
State<AnimatedProgressIndicator> createState() {
return _AnimatedProgressIndicatorState();
}
}
class _AnimatedProgressIndicatorState extends State<AnimatedProgressIndicator>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<Color?> _colorAnimation;
late Animation<double> _curveAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 1200),
vsync: this,
);
final colorTween = TweenSequence([
TweenSequenceItem(
tween: ColorTween(begin: Colors.red, end: Colors.orange),
weight: 1,
),
TweenSequenceItem(
tween: ColorTween(begin: Colors.orange, end: Colors.yellow),
weight: 1,
),
TweenSequenceItem(
tween: ColorTween(begin: Colors.yellow, end: Colors.green),
weight: 1,
),
]);
_colorAnimation = _controller.drive(colorTween);
_curveAnimation = _controller.drive(CurveTween(curve: Curves.easeIn));
}
@override
void didUpdateWidget(oldWidget) {
super.didUpdateWidget(oldWidget);
_controller.animateTo(widget.value);
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) => LinearProgressIndicator(
value: _curveAnimation.value,
valueColor: _colorAnimation,
backgroundColor: _colorAnimation.value?.withOpacity(0.4),
),
);
}
}
観察
- 使用できます
AnimationController
任意のアニメーションを実行します。 -
AnimatedBuilder
値が次の場合にウィジェット ツリーを再構築します。 のAnimation
変化します。 - を使って
Tween
、ほぼすべての値の間を補間できます。 この場合、Color
。
次は何?
おめでとう! Flutter を使用して最初の Web アプリを作成しました。
このサンプルを引き続き使用したい場合は、 おそらくフォーム検証を追加できるでしょう。 これを行う方法についてのアドバイスについては、 を参照してください検証を伴うフォームの構築のレシピ flutterクックブック。
Flutter Web アプリの詳細については、 Dart DevTools、または Flutter アニメーションについては、以下を参照してください。
- アニメーションドキュメント
- Dart 開発ツール
- 暗黙的なアニメーションコードラボ
- ウェブサンプル